package com.example.mqttclient;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import com.example.mqttclient.mqtt.MqttService;
import com.example.mqttclient.protocol.AirConditioningMessage;
import com.example.mqttclient.protocol.BoolMessage;
import com.example.mqttclient.protocol.FloatMessage;
import com.example.mqttclient.protocol.IntMessage;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.google.gson.Gson;
import org.eclipse.paho.client.mqttv3.MqttException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DevicesDemoActivity extends AppCompatActivity implements MqttService.MqttEventCallBack,
        SeekBar.OnSeekBarChangeListener {

    // UI 组件
    private TextView connectState, temperatureValue, humidityValue, pmValue, gasValue, doorStatus;
    private EditText airConditioningValue;
    private SeekBar parlourLightSeekbar, fanSocketSeekbar;
    private Switch curtainSwitch, airConditioningSwitch;

    // MQTT 相关
    private MqttService.MqttBinder mqttBinder;
    private final Map<String, Integer> subscribeTopics = new HashMap<>();
    private static final String TAG = "DevicesDemoActivity";

    // 图表相关
    private LineChart temperatureChart, humidityChart, pmChart, gasChart;
    private final List<Entry> temperatureEntries = new ArrayList<>();
    private final List<Entry> humidityEntries = new ArrayList<>();
    private final List<Entry> pmEntries = new ArrayList<>();
    private final List<Entry> gasEntries = new ArrayList<>();
    private ScheduledExecutorService scheduledExecutorService;
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    // 报警相关
    private static final int GAS_ALERT_THRESHOLD = 60;
    private boolean isGasAlertShown = false;
    private static final String CHANNEL_ID = "gas_alert_channel";
    private NotificationManager notificationManager;

    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mqttBinder = (MqttService.MqttBinder) iBinder;
            mqttBinder.setMqttEventCallBack(DevicesDemoActivity.this);
            connectState.setText(mqttBinder.isConnected() ? "已连接" : "未连接");
            if (mqttBinder.isConnected()) {
                subscribeTopics();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_devices_demo);

        // 初始化通知系统
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        createNotificationChannel();

        // 初始化UI组件
        initViews();

        // 绑定MQTT服务
        bindService(new Intent(this, MqttService.class), connection, BIND_AUTO_CREATE);

        // 初始化图表
        initCharts();

        // 启动图表更新定时任务
        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(() -> runOnUiThread(this::updateCharts),
                1, 1, TimeUnit.SECONDS);
    }

    private void initViews() {
        connectState = findViewById(R.id.dev_connect_state);
        temperatureValue = findViewById(R.id.temperature_value);
        humidityValue = findViewById(R.id.humidity_value);
        pmValue = findViewById(R.id.pm_value);
        gasValue = findViewById(R.id.gas_value);
        doorStatus = findViewById(R.id.door_status);
        airConditioningValue = findViewById(R.id.air_conditioning_value);

        parlourLightSeekbar = findViewById(R.id.parlour_light_seekbar);
        parlourLightSeekbar.setOnSeekBarChangeListener(this);
        fanSocketSeekbar = findViewById(R.id.fan_socket_seekbar);
        fanSocketSeekbar.setOnSeekBarChangeListener(this);

        curtainSwitch = findViewById(R.id.curtain_switch);
        curtainSwitch.setOnCheckedChangeListener(this::onCheckedChangedForSwitch);
        airConditioningSwitch = findViewById(R.id.air_conditioning_switch);
        airConditioningSwitch.setOnCheckedChangeListener(this::onCheckedChangedForSwitch);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "燃气警报",
                    NotificationManager.IMPORTANCE_HIGH
            );
            channel.setDescription("可燃气体浓度过高警报");
            channel.enableVibration(true);
            channel.setVibrationPattern(new long[]{0, 1000, 500, 1000});

            AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_ALARM)
                    .build();
            channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM), audioAttributes);

            notificationManager.createNotificationChannel(channel);
        }
    }

    private void initCharts() {
        temperatureChart = findViewById(R.id.temperature_chart);
        humidityChart = findViewById(R.id.humidity_chart);
        pmChart = findViewById(R.id.pm_chart);
        gasChart = findViewById(R.id.gas_chart);

        initChart(temperatureChart, "室内温度 (°C)", Color.RED);
        initChart(humidityChart, "室内湿度 (%)", Color.BLUE);
        initChart(pmChart, "PM2.5 (μg/m³)", Color.GREEN);
        initChart(gasChart, "可燃气体浓度 (%LEL)", Color.MAGENTA);
    }

    private void initChart(LineChart chart, String label, int color) {
        chart.getDescription().setEnabled(false);
        chart.setTouchEnabled(true);
        chart.setDragEnabled(true);
        chart.setScaleEnabled(true);
        chart.setDrawGridBackground(false);
        chart.setPinchZoom(true);
        chart.setBackgroundColor(Color.WHITE);

        XAxis xAxis = chart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setDrawGridLines(false);
        xAxis.setValueFormatter(new ValueFormatter() {
            @Override
            public String getAxisLabel(float value, AxisBase axis) {
                long timestamp = System.currentTimeMillis() - (long) ((10 - value) * 1000);
                return dateFormat.format(new Date(timestamp));
            }
        });
        xAxis.setGranularity(1f);
        xAxis.setLabelCount(5, true);

        YAxis leftAxis = chart.getAxisLeft();
        leftAxis.setDrawGridLines(true);
        leftAxis.setAxisMinimum(0f);
        if (label.contains("温度")) leftAxis.setAxisMaximum(50f);
        else if (label.contains("湿度")) leftAxis.setAxisMaximum(100f);
        else if (label.contains("PM2.5")) leftAxis.setAxisMaximum(500f);
        else if (label.contains("可燃气体")) leftAxis.setAxisMaximum(100f);

        YAxis rightAxis = chart.getAxisRight();
        rightAxis.setEnabled(false);

        Legend legend = chart.getLegend();
        legend.setForm(Legend.LegendForm.LINE);
        legend.setTextSize(12f);

        LineDataSet dataSet = new LineDataSet(new ArrayList<>(), label);
        dataSet.setColor(color);
        dataSet.setCircleColor(color);
        dataSet.setLineWidth(2f);
        dataSet.setCircleRadius(3f);
        dataSet.setFillAlpha(65);
        dataSet.setFillColor(color);
        dataSet.setHighLightColor(Color.rgb(244, 117, 117));
        dataSet.setDrawCircleHole(false);
        dataSet.setDrawValues(false);
        dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
        dataSet.setCubicIntensity(0.2f);

        chart.setData(new LineData(dataSet));
        chart.invalidate();
    }

    private void updateCharts() {
        updateChartData(temperatureChart, temperatureEntries);
        updateChartData(humidityChart, humidityEntries);
        updateChartData(pmChart, pmEntries);
        updateChartData(gasChart, gasEntries);
    }

    private void updateChartData(LineChart chart, List<Entry> entries) {
        LineDataSet dataSet = (LineDataSet) chart.getData().getDataSetByIndex(0);
        if (dataSet != null) {
            dataSet.setValues(entries);
            chart.getData().notifyDataChanged();
            chart.notifyDataSetChanged();
            chart.invalidate();
        }
    }

    private void addEntry(LineChart chart, List<Entry> entries, float value) {
        if (entries.size() > 10) {
            entries.remove(0);
            for (int i = 0; i < entries.size(); i++) {
                entries.get(i).setX(i);
            }
        }
        entries.add(new Entry(entries.size(), value));
        updateChartData(chart, entries);
    }

    // SeekBar 监听方法
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if (!fromUser) return;

        String topic = "";
        if (seekBar.getId() == R.id.parlour_light_seekbar) {
            topic = "/test/light1";
        } else if (seekBar.getId() == R.id.fan_socket_seekbar) {
            topic = "/test/fan1";
        }

        if (!topic.isEmpty()) {
            try {
                mqttBinder.publishMessage(topic, new Gson().toJson(new BoolMessage(progress > 0)));
            } catch (MqttException e) {
                Log.e(TAG, "发布消息失败", e);
            }
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {}

    // Switch 监听方法
    private void onCheckedChangedForSwitch(CompoundButton buttonView, boolean isChecked) {
        switch (buttonView.getId()) {
            case R.id.curtain_switch:
                publishSwitchMessage("/test/curtain1", isChecked);
                break;
            case R.id.air_conditioning_switch:
                handleAirConditioningAction(isChecked);
                break;
        }
    }

    private void publishSwitchMessage(String topic, boolean isChecked) {
        try {
            mqttBinder.publishMessage(topic, new Gson().toJson(new BoolMessage(isChecked)));
        } catch (MqttException e) {
            Log.e(TAG, "发布开关消息失败", e);
        }
    }

    private void handleAirConditioningAction(boolean isChecked) {
        try {
            float temp = Float.parseFloat(airConditioningValue.getText().toString());
            String json = new Gson().toJson(new AirConditioningMessage(isChecked, temp));
            mqttBinder.publishMessage("/test/airConditioning", json);
        } catch (NumberFormatException | MqttException e) {
            Log.e(TAG, "空调控制失败", e);
        }
    }

    // MQTT 消息回调
    @Override
    public void onMqttMessage(String topic, String message) {
        Log.d(TAG, "收到消息 - topic:" + topic + " message:" + message);
        runOnUiThread(() -> {
            Gson gson = new Gson();
            switch (subscribeTopics.getOrDefault(topic, 0)) {
                case 1: // 温度
                    float temperature = gson.fromJson(message.trim(), FloatMessage.class).value;
                    temperatureValue.setText(String.format("%.1f", temperature));
                    addEntry(temperatureChart, temperatureEntries, temperature);
                    break;
                case 2: // 湿度
                    int humidity = gson.fromJson(message.trim(), IntMessage.class).value;
                    humidityValue.setText(String.valueOf(humidity));
                    addEntry(humidityChart, humidityEntries, humidity);
                    break;
                case 3: // PM2.5
                    int pm = gson.fromJson(message.trim(), IntMessage.class).value;
                    pmValue.setText(String.valueOf(pm));
                    addEntry(pmChart, pmEntries, pm);
                    break;
                case 4: // 可燃气体
                    int gas = gson.fromJson(message.trim(), IntMessage.class).value;
                    gasValue.setText(String.valueOf(gas));
                    addEntry(gasChart, gasEntries, gas);
                    handleGasAlert(gas);
                    break;
                case 5: // 门状态
                    boolean doorOpen = gson.fromJson(message.trim(), BoolMessage.class).value;
                    doorStatus.setText(doorOpen ? "开" : "关");
                    break;
            }
        });
    }

    private void handleGasAlert(int gasValue) {
        if (gasValue > GAS_ALERT_THRESHOLD && !isGasAlertShown) {
            showGasAlertDialog(gasValue);
            isGasAlertShown = true;
        } else if (gasValue <= GAS_ALERT_THRESHOLD) {
            isGasAlertShown = false;
        }
    }

    private void showGasAlertDialog(int gasValue) {
        new AlertDialog.Builder(this)
                .setTitle("燃气泄漏警报！")
                .setMessage("检测到可燃气体浓度过高: " + gasValue + "%LEL\n请立即检查燃气设备并通风！")
                .setPositiveButton("确定", null)
                .setCancelable(false)
                .show();

        sendGasAlertNotification(gasValue);
    }

    private void sendGasAlertNotification(int gasValue) {
        Intent intent = new Intent(this, DevicesDemoActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("燃气泄漏警报！")
                .setContentText("可燃气体浓度: " + gasValue + "%LEL - 请立即处理！")
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setCategory(NotificationCompat.CATEGORY_ALARM)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM))
                .setVibrate(new long[]{0, 1000, 500, 1000})
                .build();

        notificationManager.notify(1, notification);
    }

    @Override
    public void onConnectSuccess() {
        connectState.setText("已连接");
        subscribeTopics();
    }

    @Override
    public void onConnectError(String error) {
        Log.e(TAG, "连接错误: " + error);
        connectState.setText("未连接");
        subscribeTopics.clear();
    }

    @Override
    public void onDeliveryComplete() {
        Log.d(TAG, "消息发布完成");
    }

    private void subscribeTopics() {
        try {
            subscribeTopics.put("/test/temp", 1);
            subscribeTopics.put("/test/hum", 2);
            subscribeTopics.put("/test/pm", 3);
            subscribeTopics.put("/test/gas", 4);
            subscribeTopics.put("/test/door", 5);

            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.subscribe(entry.getKey());
            }
        } catch (MqttException e) {
            Log.e(TAG, "订阅主题失败", e);
        }
    }

    private void unSubscribeTopics() {
        try {
            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.unSubscribe(entry.getKey());
            }
            subscribeTopics.clear();
        } catch (MqttException e) {
            Log.e(TAG, "取消订阅失败", e);
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        if (mqttBinder != null && mqttBinder.isConnected()) {
            connectState.setText("已连接");
            subscribeTopics();
        } else {
            connectState.setText("未连接");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        unSubscribeTopics();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (scheduledExecutorService != null) {
            scheduledExecutorService.shutdown();
        }
        unbindService(connection);
    }
}